package cn.funeralobjects.asms.web.controller;

import cn.funeralobjects.ams.web.api.ProductApiApi;
import cn.funeralobjects.ams.web.utils.ApiUtils;
import cn.funeralobjects.asms.entity.ESmsSign;
import cn.funeralobjects.asms.entity.ESmsTemplate;
import cn.funeralobjects.asms.model.SmsSendRecord;
import cn.funeralobjects.asms.service.SmsSendRecordService;
import cn.funeralobjects.asms.service.SmsSignService;
import cn.funeralobjects.asms.service.SmsTemplateService;
import cn.funeralobjects.asms.web.mapper.SmsSendRecordMapper;
import cn.funeralobjects.asms.web.model.MSmsSend;
import cn.funeralobjects.asms.web.model.MSmsSendCode;
import cn.funeralobjects.asms.web.model.VSmsSendRecord;
import cn.funeralobjects.common.service.exception.LackDataException;
import cn.funeralobjects.common.service.exception.OperationException;
import cn.funeralobjects.utils.aliyun.sms.SmsAction;
import cn.funeralobjects.utils.aliyun.sms.model.SendSmsParam;
import cn.funeralobjects.web.api.SmsSendApi;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author FuneralObjects
 * Create date: 2020/6/1 7:16 AM
 */
@RestController
@RequestMapping("/sms-send")
public class SmsSendController implements SmsSendApi {

    @Resource
    private SmsSignService smsSignService;

    @Resource
    private SmsTemplateService smsTemplateService;

    @Resource
    private ProductApiApi productApiApi;

    @Resource
    private SmsSendRecordService smsSendRecordService;
    @Resource
    private SmsSendRecordMapper smsSendRecordMapper;

    @PostMapping
    @Override
    public Mono<List<VSmsSendRecord>> sendSms(@RequestBody MSmsSend mSmsSend) {
        return Mono.just(mSmsSend)
                .flatMap(modify -> {
                    ESmsSign smsSign = smsSignService.findById(modify.getSignId()).orElseThrow(() -> new LackDataException(String.format("The Sign[%s] doesn't exists", modify.getSignId())));
                    ESmsTemplate smsTemplate = smsTemplateService.findById(modify.getTemplateId()).orElseThrow(() -> new LackDataException(String.format("The Template[%s] doesn't exists", modify.getTemplateId())));
                    return sendRecords(smsSign, smsTemplate, modify.getTelephones(), modify.getMsgParam());
                });
    }

    @PostMapping(params = "use-code")
    @Override
    public Mono<List<VSmsSendRecord>> sendSms(@RequestBody MSmsSendCode mSmsSendCode) {
        return Mono.just(mSmsSendCode)
                .flatMap(modify -> {
                    ESmsSign smsSign = smsSignService.findByCode(modify.getSignCode()).orElseThrow(() -> new LackDataException(String.format("The Sign[%s] doesn't exists", modify.getSignCode())));
                    ESmsTemplate smsTemplate = smsTemplateService.findByCode(modify.getTemplateCode()).orElseThrow(() -> new LackDataException(String.format("The Template[%s] doesn't exists", modify.getTemplateCode())));
                    return sendRecords(smsSign, smsTemplate, modify.getTelephones(), modify.getMsgParam());
                });
    }

    private Mono<List<VSmsSendRecord>> sendRecords(ESmsSign smsSign, ESmsTemplate smsTemplate, List<String> telephones, Map<String, String> params) {
        if (!smsSign.getProdResCode().equals(smsTemplate.getProdResCode())) {
            return Mono.error(new OperationException("The sign[%s] doesn't match the Template[%s]"));
        }
        return ApiUtils.createClient(smsSign.getProdResCode(), SmsAction.SEND_SMS, productApiApi)
                .map(client -> {
                    SendSmsParam param = new SendSmsParam().setPhoneNumbers(telephones)
                            .setTemplateParam(params)
                            .setSignName(smsSign.getSignName())
                            .setTemplateCode(smsTemplate.getTemplateCode());
                    return ApiUtils.doAction(client, param);
                })
                .map(data -> smsSendRecordService.addInBatch(telephones
                        .stream()
                        .map(telephone -> new SmsSendRecord()
                                .setSmsBizId(data.getBizId())
                                .setSmsSignId(smsSign.getId())
                                .setSmsErrCode(data.getCode())
                                .setSmsErrMessage(data.getMessage())
                                .setSmsTemplateId(smsTemplate.getId())
                                .setSmsSendParam(new Gson().toJson(params))
                                .setSmsSendTelephone(telephone)
                        ).collect(Collectors.toList())).stream().map(smsSendRecordMapper::toVo).collect(Collectors.toList()));
    }
}
